`timescale 1ns / 1ps
`include "InstrHeader.h"
`default_nettype none
//////////////////////////////////////////////////////////////////////////////////
// Company: 
// Engineer: 
// 
// Create Date: 2019/07/03 11:16:09
// Design Name: 
// Module Name: ExecuteSdate
// Project Name: 
// Target Devices: 
// Tool Versions: 
// Description: 
// 
// Dependencies: 
// 
// Revision:
// Revision 0.01 - File Created
// Additional Comments:
// 
//////////////////////////////////////////////////////////////////////////////////


module ExecuteSdate(
    input   wire	Clk,
    input   wire	Clr,
	input	wire	[31:0]	D_PC,
	input	wire	[31:0]	D_Instr,
    input   wire	[4:0]   D_RsID,
    input   wire	[4:0]   D_RtID,
    input   wire	[31:0]  D_RsData,
    input 	wire	[31:0]  D_RtData,
    input   wire	[4:0]   D_Shamt,
    input   wire	[15:0]  D_Imm16,
    input	wire	[`InstrBusWidth]  D_InstrBus,
    input 	wire	[3:0]   D_T,
    input	wire	D_WriteRegEnable,
    input	wire	[4:0]   D_RegId,
    
    input   wire    M_WriteRegEnable,
    input   wire	[4:0]   M_RegId,
    input   wire	[31:0]  M_Data,

	output	reg	[31:0]	E_PC,
	output	reg [31:0]	E_Instr,
    output	reg [31:0]   E_WriteMemData,
    output	reg [4:0]    E_RtID,

    output	reg	[3:0]   E_T,
    output	reg			E_WriteRegEnable,
    output	reg	[4:0]	E_RegId,
    output	reg	[31:0]  E_Data,

    
    output	reg	[3:0]   E_MemBitEnable,
	output	reg			E_MemReadEnable,
    output	reg			E_MemWriteEnable,
	output	reg	[4:0]   E_ExtType,

	output	wire		E_XALU_Busy,

	output	wire	[31:0]	E_MemAddr_Pass// for Mem
    );
	wire	`InstrBusWireSet;
	assign	{`InstrBusWireSet}	=	D_InstrBus;


    /////////////////////转发////////////////
    wire    [31:0]  MF_Rs = (D_RsID!=0 && D_RsID==E_RegId && E_T==0 && E_WriteRegEnable)		?   E_Data:
                            (D_RsID!=0 && M_WriteRegEnable && M_RegId==D_RsID)								?   M_Data:
                                                                                                    D_RsData;
    wire    [31:0]  MF_Rt = (D_RtID!=0 && D_RtID==E_RegId && E_T==0 && E_WriteRegEnable)		?	E_Data:
                            (D_RtID!=0 && M_WriteRegEnable && M_RegId==D_RtID)								?   M_Data://M级结束（实际上是W级了），那么T必定�
                                                                                                    D_RtData;
    	/////////////////////For Mem Addr/////
	wire [31:0] ext_imm32 = {{16{D_Imm16[15]}},D_Imm16};
	wire [31:0] MemAddr = ext_imm32+MF_Rt;
	assign E_MemAddr_Pass = MemAddr;
	////////////////////////////////////////


    wire    [31:0]  C_Inter;
    ALU ALU(.A(MF_Rs),.B(MF_Rt),.shamt(D_Shamt),.Imm16(D_Imm16),.InstrBus(D_InstrBus),.C(C_Inter),.PC(D_PC));

	wire [31:0] XALU_HI,
				XALU_LO;
	wire		XALU_Busy_Inter;
	
	XALU XALU(.Clk(Clk),.Clr(Clr),.InstrBus(D_InstrBus),.XALU_A(MF_Rs),.XALU_B(MF_Rt),.XALU_HI(XALU_HI),.XALU_LO(XALU_LO),.XALU_Busy(XALU_Busy_Inter));

	wire	[1:0]	Offset = C_Inter[1:0];
    wire    [4:0]   ExtType_Inter;
	wire	[3:0]	MemBitEnable_Inter;
    wire			MemWriteEnable_Inter;
    wire    		MemReadEnable_Inter;
    MemCtrlUnit MemCtrlUnit(.InstrBus(D_InstrBus),
							.Offset(Offset),
							.ExtType(ExtType_Inter),
							.MemBitEnable(MemBitEnable_Inter),
							.MemReadEnable(MemReadEnable_Inter),
							.MemWriteEnable(MemWriteEnable_Inter));
    //////////////////////////////////////////////////////////////////////////////////////////
    wire    [3:0] E_T_Inter = (D_T > 0)?D_T-1:0;
	wire	[31:0]	Data_Inter = 	mfhi	?	XALU_HI:
									mflo	?	XALU_LO:
												C_Inter;
    
    always @ (posedge Clk) begin
        if(Clr) begin
			E_PC <= 0;
			E_Instr<=0;
			E_WriteMemData <= 0;
			E_RtID <= 0;
			E_T <= 0;
			E_WriteRegEnable <= 0;
			E_RegId <= 0;
			E_Data <= 0;
			E_ExtType <= 0;
			E_MemReadEnable <= 0;
			E_MemWriteEnable <= 0;
			E_MemBitEnable <= 0;
		end
		else begin
			E_PC <= D_PC;
			E_Instr<=D_Instr;
			E_WriteMemData <= (MF_Rt<<({Offset,3'b0}));
			E_RtID <= D_RtID;
			E_T <= D_T ==4'b0 ? 4'b0 : D_T-1;
			E_WriteRegEnable <= D_WriteRegEnable;
			E_RegId <= D_RegId;
			E_Data <= Data_Inter;
			E_ExtType <= ExtType_Inter;
			E_MemReadEnable <= MemReadEnable_Inter;
			E_MemWriteEnable <= MemWriteEnable_Inter;
			E_MemBitEnable <= MemBitEnable_Inter;
		end
		
    end
		assign E_XALU_Busy = XALU_Busy_Inter;

endmodule
